home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / examples / origami.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  8KB  |  404 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994. */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <GL/glut.h>
  11.  
  12. /* Uses EXT_polygon_offset extension if available to better
  13.    render the fold outlines. */
  14.  
  15. #if GL_EXT_polygon_offset
  16. int polygon_offset;
  17. #endif
  18.  
  19. enum {
  20.   FLAT,                 /* completely flat sheet of paper */
  21.   FLAP1,                /* left flap being folded in */
  22.   FLAP2,                /* right flap being folded int */
  23.   CENTER2,              /* right side folded up at center */
  24.   WING2,                /* right wing folded down */
  25.   CENTER1,              /* left side folded up at center */
  26.   WING1,                /* left wing folded down */
  27.   FOLDED                /* fully folded paper airplane */
  28. } States;
  29.  
  30. int motion = 1;
  31. int spinning = 1;
  32. int state = FLAT;
  33. int click = 0;
  34. int delay = 0;
  35. int direction;
  36. float flap1_angle = 0;
  37. float flap2_angle = 0;
  38. float center1_angle = 0;
  39. float center2_angle = 0;
  40. float wing1_angle = 0;
  41. float wing2_angle = 0;
  42.  
  43. /**
  44.  
  45. These correspond to the polygons for the paper sections:
  46.  
  47.   +----------+----------+
  48.   |         /|\         |
  49.   |  2     / | \    3   |
  50.   |       /  |  \       |
  51.   +------/   |   \------+
  52.   |     /|   |   |\     |
  53.   | 1  / |   |   | \ 4  |
  54.   |   /  |   |   |  \   |
  55.   |  /   |   |   |   \  |
  56.   | /    | 5 | 6 |    \ |
  57.   |/     |   |   |     \|
  58.   +      |   |   |      +
  59.   |  7   |   |   |  8   |
  60.   |      |   |   |      |
  61.   |      |   |   |      |
  62.   |      |   |   |      |
  63.   |      |   |   |      |
  64.   |      |   |   |      |
  65.   |      |   |   |      |
  66.   +------+---+---+------+
  67.  
  68. */
  69.  
  70. typedef GLfloat Point[2];
  71.  
  72. Point poly1[] =
  73. {
  74.   {-1, 0},
  75.   {-1 / 3.0, 2 / 3.0},
  76.   {-1, 2 / 3.0}
  77. };
  78.  
  79. Point poly2[] =
  80. {
  81.   {-1, 1},
  82.   {-1, 2 / 3.0},
  83.   {-1 / 3.0, 2 / 3.0},
  84.   {0, 1}
  85. };
  86.  
  87. Point poly3[] =
  88. {
  89.   {0, 1},
  90.   {1, 1},
  91.   {1, 2 / 3.0},
  92.   {1 / 3.0, 2 / 3.0}
  93. };
  94.  
  95. Point poly4[] =
  96. {
  97.   {1 / 3.0, 2 / 3.0},
  98.   {1, 2 / 3.0},
  99.   {1, 0}
  100. };
  101.  
  102. Point poly5[] =
  103. {
  104.   {-1 / 3.0, 2 / 3.0},
  105.   {0, 1},
  106.   {0, -1.5},
  107.   {-1 / 3.0, -1.5}
  108. };
  109.  
  110. Point poly6[] =
  111. {
  112.   {0, 1},
  113.   {1 / 3.0, 2 / 3.0},
  114.   {1 / 3.0, -1.5},
  115.   {0, -1.5}
  116. };
  117.  
  118. Point poly7[] =
  119. {
  120.   {-1, 0},
  121.   {-1 / 3.0, 2 / 3.0},
  122.   {-1 / 3.0, -1.5},
  123.   {-1, -1.5}
  124. };
  125.  
  126. Point poly8[] =
  127. {
  128.   {1, 0},
  129.   {1 / 3.0, 2 / 3.0},
  130.   {1 / 3.0, -1.5},
  131.   {1, -1.5}
  132. };
  133.  
  134. void
  135. polydlist(int dlist, int num, Point points[])
  136. {
  137.   int i;
  138.  
  139.   glNewList(dlist, GL_COMPILE);
  140.   glBegin(GL_POLYGON);
  141.   for (i = 0; i < num; i++) {
  142.     glVertex2fv(&points[i][0]);
  143.   }
  144.   glEnd();
  145.   glEndList();
  146. }
  147.  
  148. void
  149. idle(void)
  150. {
  151.   if (spinning)
  152.     click++;
  153.   switch (state) {
  154.   case FLAT:
  155.     delay++;
  156.     if (delay >= 80) {
  157.       delay = 0;
  158.       state = FLAP1;
  159.       glutSetWindowTitle("origami (folding)");
  160.       direction = 1;
  161.     }
  162.     break;
  163.   case FLAP1:
  164.     flap1_angle += 2 * direction;
  165.     if (flap1_angle >= 180) {
  166.       state = FLAP2;
  167.     } else if (flap1_angle <= 0) {
  168.       state = FLAT;
  169.     }
  170.     break;
  171.   case FLAP2:
  172.     flap2_angle += 2 * direction;
  173.     if (flap2_angle >= 180) {
  174.       state = CENTER2;
  175.     } else if (flap2_angle <= 0) {
  176.       state = FLAP1;
  177.     }
  178.     break;
  179.   case CENTER2:
  180.     center2_angle += 2 * direction;
  181.     if (center2_angle >= 84) {
  182.       state = WING2;
  183.     } else if (center2_angle <= 0) {
  184.       state = FLAP2;
  185.     }
  186.     break;
  187.   case WING2:
  188.     wing2_angle += 2 * direction;
  189.     if (wing2_angle >= 84) {
  190.       state = CENTER1;
  191.     } else if (wing2_angle <= 0) {
  192.       state = CENTER2;
  193.     }
  194.     break;
  195.   case CENTER1:
  196.     center1_angle += 2 * direction;
  197.     if (center1_angle >= 84) {
  198.       state = WING1;
  199.     } else if (center1_angle <= 0) {
  200.       state = WING2;
  201.     }
  202.     break;
  203.   case WING1:
  204.     wing1_angle += 2 * direction;
  205.     if (wing1_angle >= 84) {
  206.       state = FOLDED;
  207.     } else if (wing1_angle <= 0) {
  208.       state = CENTER1;
  209.     }
  210.     break;
  211.   case FOLDED:
  212.     delay++;
  213.     if (delay >= 80) {
  214.       delay = 0;
  215.       glutSetWindowTitle("origami (unfolding)");
  216.       direction = -1;
  217.       state = WING1;
  218.     }
  219.     break;
  220.   }
  221.   glutPostRedisplay();
  222. }
  223.  
  224. void
  225. draw_folded_plane(void)
  226. {
  227.   /* *INDENT-OFF* */
  228.   glPushMatrix();
  229.     glRotatef(click, 0, 0, 1);
  230.     glRotatef(click / 5.0, 0, 1, 0);
  231.     glTranslatef(0, .25, 0);
  232.     glPushMatrix();
  233.       glRotatef(center1_angle, 0, 1, 0);
  234.       glPushMatrix();
  235.         glTranslatef(-.5, .5, 0);
  236.         glRotatef(flap1_angle, 1, 1, 0);
  237.         glTranslatef(.5, -.5, 0);
  238.         glCallList(2);
  239.       glPopMatrix();
  240.       glCallList(5);
  241.  
  242.       glPushMatrix();
  243.         glTranslatef(-1 / 3.0, 0, 0);
  244.         glRotatef(-wing1_angle, 0, 1, 0);
  245.         glTranslatef(1 / 3.0, 0, 0);
  246.  
  247.         glCallList(7);
  248.         glPushMatrix();
  249.           glTranslatef(-.5, .5, 0);
  250.           glRotatef(flap1_angle, 1, 1, 0);
  251.           glTranslatef(.5, -.5, 0);
  252.           glCallList(1);
  253.         glPopMatrix();
  254.       glPopMatrix();
  255.     glPopMatrix();
  256.  
  257.     glPushMatrix();
  258.       glRotatef(-center2_angle, 0, 1, 0);
  259.       glPushMatrix();
  260.         glTranslatef(.5, .5, 0);
  261.         glRotatef(-flap2_angle, -1, 1, 0);
  262.         glTranslatef(-.5, -.5, 0);
  263.         glCallList(3);
  264.       glPopMatrix();
  265.       glCallList(6);
  266.  
  267.       glPushMatrix();
  268.         glTranslatef(1 / 3.0, 0, 0);
  269.         glRotatef(wing2_angle, 0, 1, 0);
  270.         glTranslatef(-1 / 3.0, 0, 0);
  271.  
  272.         glCallList(8);
  273.         glPushMatrix();
  274.           glTranslatef(.5, .5, 0);
  275.           glRotatef(-flap2_angle, -1, 1, 0);
  276.           glTranslatef(-.5, -.5, 0);
  277.           glCallList(4);
  278.         glPopMatrix();
  279.       glPopMatrix();
  280.     glPopMatrix();
  281.   glPopMatrix();
  282.   /* *INDENT-ON* */
  283.  
  284. }
  285.  
  286. void
  287. display(void)
  288. {
  289.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  290.   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  291.   glColor3ub(67, 205, 128);
  292. #if GL_EXT_polygon_offset
  293.   if (polygon_offset) {
  294.     glPolygonOffsetEXT(0.5, 0.0);
  295.     glEnable(GL_POLYGON_OFFSET_EXT);
  296.   }
  297. #endif
  298.   draw_folded_plane();
  299.   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  300.   glColor3ub(255, 255, 255);
  301. #if GL_EXT_polygon_offset
  302.   if (polygon_offset) {
  303.     glPolygonOffsetEXT(0.0, 0.0);
  304.     /* XXX a bug in the unpatched IRIX 5.3 OpenGL posts
  305.        GL_INVALID_ENUM when GL_POLYGON_OFFSET_EXT is disabled;
  306.        please ignore it. */
  307.     glDisable(GL_POLYGON_OFFSET_EXT);
  308.   } else {
  309.     glPushMatrix();
  310.     glTranslatef(0, 0, .05);
  311.   }
  312. #else
  313.   glPushMatrix();
  314.   glTranslatef(0, 0, .05);
  315. #endif
  316.   draw_folded_plane();
  317. #if GL_EXT_polygon_offset
  318.   if (!polygon_offset) {
  319.     glPopMatrix();
  320.   }
  321. #else
  322.   glPopMatrix();
  323. #endif
  324.   glutSwapBuffers();
  325. }
  326.  
  327. void
  328. visible(int state)
  329. {
  330.   if (state == GLUT_VISIBLE) {
  331.     if (motion)
  332.       glutIdleFunc(idle);
  333.   } else {
  334.     glutIdleFunc(NULL);
  335.   }
  336. }
  337.  
  338. void
  339. menu(int value)
  340. {
  341.   switch (value) {
  342.   case 1:
  343.     direction = -direction;
  344.     if (direction > 0) {
  345.       glutSetWindowTitle("origami (folding)");
  346.     } else {
  347.       glutSetWindowTitle("origami (unfolding)");
  348.     }
  349.     break;
  350.   case 2:
  351.     motion = 1 - motion;
  352.     if (motion) {
  353.       glutIdleFunc(idle);
  354.     } else {
  355.       glutIdleFunc(NULL);
  356.     }
  357.     break;
  358.   case 3:
  359.     spinning = 1 - spinning;
  360.     break;
  361.   case 666:
  362.     exit(0);
  363.   }
  364. }
  365.  
  366. int
  367. main(int argc, char **argv)
  368. {
  369.   glutInit(&argc, argv);
  370.   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  371.   glutCreateWindow("origami");
  372.   glutDisplayFunc(display);
  373.   glutVisibilityFunc(visible);
  374.   glClearColor(.488, .617, .75, 1.0);
  375.   glMatrixMode(GL_PROJECTION);
  376.   gluPerspective(40.0, 1.0, 0.1, 10.0);
  377.   glMatrixMode(GL_MODELVIEW);
  378.   gluLookAt(0, 0, 5.5,
  379.     0, 0, 0,
  380.     0, 1, 0);
  381.   glEnable(GL_DEPTH_TEST);
  382.   glDepthFunc(GL_LEQUAL);
  383.   glLineWidth(2.0);
  384.   polydlist(1, sizeof(poly1) / sizeof(Point), poly1);
  385.   polydlist(2, sizeof(poly2) / sizeof(Point), poly2);
  386.   polydlist(3, sizeof(poly3) / sizeof(Point), poly3);
  387.   polydlist(4, sizeof(poly4) / sizeof(Point), poly4);
  388.   polydlist(5, sizeof(poly5) / sizeof(Point), poly5);
  389.   polydlist(6, sizeof(poly6) / sizeof(Point), poly6);
  390.   polydlist(7, sizeof(poly7) / sizeof(Point), poly7);
  391.   polydlist(8, sizeof(poly8) / sizeof(Point), poly8);
  392.   glutCreateMenu(menu);
  393.   glutAddMenuEntry("Reverse direction", 1);
  394.   glutAddMenuEntry("Toggle motion", 2);
  395.   glutAddMenuEntry("Toggle spinning", 3);
  396.   glutAddMenuEntry("Quit", 666);
  397.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  398. #if GL_EXT_polygon_offset
  399.   polygon_offset = glutExtensionSupported("GL_EXT_polygon_offset");
  400. #endif
  401.   glutMainLoop();
  402.   return 0;             /* ANSI C requires main to return int. */
  403. }
  404.